{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "stuffed-northeast",
   "metadata": {},
   "outputs": [],
   "source": [
    "from dwave.system import DWaveSampler, EmbeddingComposite\n",
    "from greedy import SteepestDescentComposite\n",
    "import sys, os\n",
    "sys.path.append(\"../\")\n",
    "from bqm_input_checker import InputChecker\n",
    "from btor2bqm import BTor2BQM"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "arctic-cotton",
   "metadata": {},
   "source": [
    "# 32 bit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "consecutive-cycling",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "started building ../../../qa_examples/32_d.btor2 for 10 timesteps\n",
      "{'size_datasegment': 1, 'size_heap': 3, 'size_stack': 20, 'begin_datasegment': 17408, 'begin_heap': 18432, 'word_size': 32, 'address_step_size': 1, 'address_word_size': 30, 'begin_stack': 1073741824}\n",
      "output dir:  ./32_d/\n",
      "sort memory modified to be bitvector of size:  768\n",
      "0.17 1414\n"
     ]
    }
   ],
   "source": [
    "parser = BTor2BQM(10)\n",
    "bqm_32, total_time_32, num_variables_32 = parser.parse_file(f\"../../../qa_examples/32_d.btor2\",\n",
    "                          f\"./32_d/\",\n",
    "                          with_init=True, modify_memory_sort=True)\n",
    "print(total_time_32, num_variables_32)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "polyphonic-adrian",
   "metadata": {},
   "source": [
    "# 64 bit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "opponent-prevention",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "started building ../../../qa_examples/64_d.btor2 for 10 timesteps\n",
      "{'size_datasegment': 1, 'size_heap': 2, 'size_stack': 15, 'begin_datasegment': 8704, 'begin_heap': 9216, 'word_size': 64, 'address_step_size': 1, 'address_word_size': 29, 'begin_stack': 536870912}\n",
      "output dir:  ./64_d/\n",
      "sort memory modified to be bitvector of size:  1152\n",
      "0.36 2790\n"
     ]
    }
   ],
   "source": [
    "parser = BTor2BQM(10)\n",
    "bqm_64, total_time_64, num_variables_64 = parser.parse_file(f\"../../../qa_examples/64_d.btor2\",\n",
    "                          f\"./64_d/\",\n",
    "                          with_init=True, modify_memory_sort=True)\n",
    "print(total_time_64, num_variables_64)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "rolled-detail",
   "metadata": {},
   "source": [
    "# Minor Embedding"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "personal-census",
   "metadata": {},
   "outputs": [],
   "source": [
    "import minorminer\n",
    "import dimod\n",
    "import dwave_networkx as dnx\n",
    "problem_graph_32 = dimod.to_networkx_graph(bqm_32)\n",
    "problem_graph_64 = dimod.to_networkx_graph(bqm_64)\n",
    "chimera_graph = dnx.chimera_graph(16)\n",
    "pegasus_graph = dnx.pegasus_graph(16)\n",
    "\n",
    "def get_count_embedding_physical_variables(embedding):\n",
    "    result = 0\n",
    "    for (key, ancillas) in embedding.items():\n",
    "        result += len(ancillas)\n",
    "    return result\n",
    "def get_chain_lengths(embedding):\n",
    "    result = []\n",
    "    for (key, ancillas) in embedding.items():\n",
    "        result.append(len(ancillas))\n",
    "    return result\n",
    "\n",
    "import time\n",
    "import random\n",
    "def get_statistics_embedding(target_graph, source_graph, num_runs, seed=1):\n",
    "    random.seed(seed)\n",
    "    times = []\n",
    "    distribution_chain_lengths = []\n",
    "    vars_in_qpu = []\n",
    "    for _ in range(num_runs):\n",
    "        embedding_seed = random.randint(0, 10000)\n",
    "        t0 = time.perf_counter()\n",
    "        embedding =  minorminer.find_embedding(source_graph, target_graph, random_seed=embedding_seed)\n",
    "        t1 = time.perf_counter()\n",
    "        times.append(round(t1-t0, 2))\n",
    "        vars_in_qpu.append(get_count_embedding_physical_variables(embedding))\n",
    "        distribution_chain_lengths.extend(get_chain_lengths(embedding))\n",
    "    return times, distribution_chain_lengths, vars_in_qpu\n",
    "\n",
    "import statistics\n",
    "import pandas as pd\n",
    "COL_FILE_NAME = 'file_name'\n",
    "COL_WORDSIZE = 'wordsize'\n",
    "COL_LOGIC_VARS = 'logic_vars'\n",
    "COL_TOPOLOGY = 'topology'\n",
    "\n",
    "COL_EMB_MAX_TIME = 'emb_max_time'\n",
    "COL_EMB_MIN_TIME = 'emb_min_time'\n",
    "COL_EMB_MEDIAN_TIME = 'emb_median_time'\n",
    "COL_EMB_AVG_TIME = 'emb_avg_time'\n",
    "\n",
    "COL_EMB_MAX_CHAIN = 'emb_max_chain'\n",
    "COL_EMB_MIN_CHAIN = 'emb_min_chain'\n",
    "COL_EMB_MEDIAN_CHAIN = 'emb_median_chain'\n",
    "COL_EMB_AVG_CHAIN = 'emb_avg_chain'\n",
    "\n",
    "COL_EMB_MAX_VARS = 'emb_max_vars'\n",
    "COL_EMB_MIN_VARS = 'emb_min_vars'\n",
    "COL_EMB_MEDIAN_VARS = 'emb_median_vars'\n",
    "COL_EMB_AVG_VARS = 'emb_avg_vars'\n",
    "\n",
    "columns = [COL_FILE_NAME, COL_WORDSIZE, COL_LOGIC_VARS, COL_EMB_MAX_TIME, COL_EMB_MIN_TIME, \n",
    "           COL_EMB_MEDIAN_TIME, COL_EMB_AVG_TIME, COL_EMB_MAX_CHAIN, \n",
    "           COL_EMB_MIN_CHAIN, COL_EMB_MEDIAN_CHAIN, COL_EMB_AVG_CHAIN,\n",
    "          COL_EMB_MAX_VARS, COL_EMB_MIN_VARS, COL_EMB_MEDIAN_VARS, COL_EMB_AVG_VARS]\n",
    "\n",
    "data_embedding = pd.DataFrame(columns=columns)\n",
    "def add_embedding_statistics_row(filename, wordsize, topology, logic_vars, times, chains, vars_qpu):\n",
    "    times.sort()\n",
    "    chains.sort()\n",
    "    vars_qpu.sort()\n",
    "    \n",
    "    row = {\n",
    "        COL_FILE_NAME: filename,\n",
    "        COL_WORDSIZE: wordsize,\n",
    "        COL_LOGIC_VARS: logic_vars,\n",
    "        COL_TOPOLOGY: topology,\n",
    "        \n",
    "        COL_EMB_MAX_TIME: max(times),\n",
    "        COL_EMB_MIN_TIME: min(times),\n",
    "        COL_EMB_MEDIAN_TIME: round(statistics.median(times),2),\n",
    "        COL_EMB_AVG_TIME: round(sum(times)/len(times),2),\n",
    "        \n",
    "        COL_EMB_MAX_CHAIN: max(chains),\n",
    "        COL_EMB_MIN_CHAIN: min(chains),\n",
    "        COL_EMB_MEDIAN_CHAIN: round(statistics.median(chains),2),\n",
    "        COL_EMB_AVG_CHAIN: round(sum(chains)/len(chains),2),\n",
    "        \n",
    "        COL_EMB_MAX_VARS: max(vars_qpu),\n",
    "        COL_EMB_MIN_VARS: min(vars_qpu),\n",
    "        COL_EMB_MEDIAN_VARS: round(statistics.median(vars_qpu),2),\n",
    "        COL_EMB_AVG_VARS: round(sum(vars_qpu)/len(vars_qpu),2),\n",
    "    }\n",
    "    return data_embedding.append(row, ignore_index=True)\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "democratic-attempt",
   "metadata": {},
   "source": [
    "## Pegasus "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "attempted-jewel",
   "metadata": {},
   "outputs": [],
   "source": [
    "pegasus_times_32, pegasus_chain_length_32, pegasus_physical_vars_32 = get_statistics_embedding(pegasus_graph, problem_graph_32, 1)\n",
    "data_embedding = add_embedding_statistics_row('d.btor2', 32, 'pegasus', num_variables_32, pegasus_times_32, pegasus_chain_length_32, pegasus_physical_vars_32)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "confidential-profit",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>file_name</th>\n",
       "      <th>wordsize</th>\n",
       "      <th>logic_vars</th>\n",
       "      <th>emb_max_time</th>\n",
       "      <th>emb_min_time</th>\n",
       "      <th>emb_median_time</th>\n",
       "      <th>emb_avg_time</th>\n",
       "      <th>emb_max_chain</th>\n",
       "      <th>emb_min_chain</th>\n",
       "      <th>emb_median_chain</th>\n",
       "      <th>emb_avg_chain</th>\n",
       "      <th>emb_max_vars</th>\n",
       "      <th>emb_min_vars</th>\n",
       "      <th>emb_median_vars</th>\n",
       "      <th>emb_avg_vars</th>\n",
       "      <th>topology</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>d.btor2</td>\n",
       "      <td>32</td>\n",
       "      <td>1414</td>\n",
       "      <td>411.4</td>\n",
       "      <td>411.4</td>\n",
       "      <td>411.4</td>\n",
       "      <td>411.4</td>\n",
       "      <td>62</td>\n",
       "      <td>1</td>\n",
       "      <td>2.0</td>\n",
       "      <td>3.18</td>\n",
       "      <td>4498</td>\n",
       "      <td>4498</td>\n",
       "      <td>4498</td>\n",
       "      <td>4498.0</td>\n",
       "      <td>pegasus</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  file_name wordsize logic_vars  emb_max_time  emb_min_time  emb_median_time  \\\n",
       "0   d.btor2       32       1414         411.4         411.4            411.4   \n",
       "\n",
       "   emb_avg_time emb_max_chain emb_min_chain  emb_median_chain  emb_avg_chain  \\\n",
       "0         411.4            62             1               2.0           3.18   \n",
       "\n",
       "  emb_max_vars emb_min_vars emb_median_vars  emb_avg_vars topology  \n",
       "0         4498         4498            4498        4498.0  pegasus  "
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data_embedding"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "contemporary-democrat",
   "metadata": {},
   "outputs": [],
   "source": [
    "data_embedding.to_csv('d_embedding.csv')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "effective-czech",
   "metadata": {},
   "source": [
    "# Simulated Annealing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "scenic-flashing",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 18.0\n"
     ]
    }
   ],
   "source": [
    "import neal\n",
    "sampler = neal.SimulatedAnnealingSampler()\n",
    "simulated_samples_32 = sampler.sample(bqm_32,num_reads=10000, seed=7).lowest()\n",
    "print(len(simulated_samples_32.lowest()), simulated_samples_32.first.energy)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ambient-resolution",
   "metadata": {},
   "source": [
    "# Quantum Annealing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "lucky-decision",
   "metadata": {},
   "outputs": [],
   "source": [
    "from dwave.system import DWaveSampler, EmbeddingComposite\n",
    "from greedy import SteepestDescentComposite\n",
    "ADVANTAGE = \"Advantage_system4.1\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "industrial-spray",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "341.48 102.0 1\n"
     ]
    }
   ],
   "source": [
    "t0 = time.perf_counter()\n",
    "qpu = EmbeddingComposite(DWaveSampler(solver={\"name\": ADVANTAGE}))\n",
    "sampler = SteepestDescentComposite(qpu)\n",
    "result = sampler.sample(bqm_32, num_reads=7000, chain_strength=1.5)\n",
    "t1 = time.perf_counter()\n",
    "print(round(t1-t0,2), result.first.energy, len(result.lowest()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "hourly-member",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1021.91 126.0 2\n"
     ]
    }
   ],
   "source": [
    "t0 = time.perf_counter()\n",
    "qpu = EmbeddingComposite(DWaveSampler(solver={\"name\": ADVANTAGE}))\n",
    "sampler = SteepestDescentComposite(qpu)\n",
    "result = sampler.sample(bqm_32, num_reads=7000, chain_strength=2)\n",
    "t1 = time.perf_counter()\n",
    "print(round(t1-t0,2), result.first.energy, len(result.lowest()))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
